package io.esirong.widget.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.NonNull;


/**
 * 倒计时控件
 * Created by esirong on 2016/9/9.
 */
public class CountDownView extends View {
    private final TextPaint mTextPaint = new TextPaint();
    private final TextPaint mDivPaint = new TextPaint();
    private final TextPaint mBgPaint = new TextPaint();
    private boolean inited = false;
    int hour;
    int minute;
    int second;
    RectF rectF = new RectF();
    private long mTimeMillis;// the currently displayed time
    private boolean mStarted;
    private boolean isIdle;
    private CountDownTimer downTimer;
    private float mTextSize = sp2px(getContext(), 16);
    private TimeBlock timeBlock;
    private OnTickListener tickListener;

    public CountDownView(Context context) {
        this(context, null);
    }

    public CountDownView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CountDownView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
        //初始预设值
        initTimeTextPaint();
        initTimeTextBg();
        mDivPaint.setAntiAlias(true);
        mDivPaint.setTextAlign(Paint.Align.CENTER);
        mDivPaint.setTextSize(mTextSize);

        downTimer = new CountDownTimer(mTimeMillis, 1000);

        downTimer.setOnTickListener(new CountDownTimer.OnTickListener() {
            @Override
            public void onTick(CountDownTimer countDownTimer) {
                updateText(countDownTimer.getMillisRemind());
                if (tickListener != null) {
                    tickListener.onTick(CountDownView.this);
                }
            }

            @Override
            public void onComplete(CountDownTimer countDownTimer) {
                if (tickListener != null) {
                    tickListener.onComplete(CountDownView.this);
                }
            }
        });
    }

    //初计时始画笔
    private void initTimeTextPaint() {
        //
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        mTextPaint.setFakeBoldText(true);
        mTextPaint.setColor(Color.WHITE);
    }

    private float sp2px(Context context, float spValue) {
        if (spValue <= 0) {
            return 0;
        }
        final float scale = context.getResources().getDisplayMetrics().scaledDensity;
        return spValue * scale;
    }

    public int dp2px(Context context, float dpValue) {
        if (dpValue <= 0) {
            return 0;
        }
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    //初始计时器的背景
    private void initTimeTextBg() {
        mBgPaint.setAntiAlias(true);
        mBgPaint.setColor(Color.parseColor("#ff9933"));

        mDivPaint.setColor(Color.parseColor("#ff9933"));
    }

    public void setTime(long timeMillis) {
        mTimeMillis = timeMillis;
    }

    /**
     * 开始倒计
     */
    public void start() {
        isIdle = false;
        mStarted = true;
        downTimer.start();
    }

    public void stop() {
        isIdle = false;
        mStarted = false;
        downTimer.stop();

    }

    public void setIdle() {
        stop();
        isIdle = true;
    }

    private int getDesiredWidth() {
        int result;
        timeBlock = new TimeBlock();
        result = timeBlock.width() * 6;//所需要的最小包裹宽度值
        result += timeBlock.getDivWidth() * 2;//所需要的最小包裹宽度值

        return result;

    }

    private int getDesiredHeight() {
        int result;
        timeBlock = new TimeBlock();
        result = timeBlock.height();//所需要的最小包裹高度值
        return result;

    }

    private String formatNumH(int time) {
        if (isIdle && !mStarted) {
            return "-";
        }
        return String.valueOf(time / 10);
    }

    private String formatNumL(int time) {
        if (isIdle && !mStarted) {
            return "-";
        }
        return String.valueOf(time % 10);

    }

    /**
     * start countdown
     *
     * @param millisecond millisecond
     */
    public void start(long millisecond) {
        downTimer.start(millisecond);
    }

    private synchronized void updateText(long ms) {
        // hour = (int) ((ms % (1000 * 60 * 60 * 99)) / (1000 * 60 * 60));//时位不限制24小制,bug
        hour = (int) (ms / 1000 / 60 / 60);
        if (hour >= 100) {
            hour = 99;
        }
        minute = (int) ((ms % (1000 * 60 * 60)) / (1000 * 60));
        second = (int) ((ms % (1000 * 60)) / 1000);

        invalidate();

    }

    @Override
    protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制背景
        if(!inited){
            canvas.drawRoundRect(timeBlock.getRectFBg(0), 6, 6, mBgPaint);
            canvas.drawRoundRect(timeBlock.getRectFBg(1), 6, 6, mBgPaint);
            canvas.drawRoundRect(timeBlock.getRectFBg(2), 6, 6, mBgPaint);
            canvas.drawRoundRect(timeBlock.getRectFBg(3), 6, 6, mBgPaint);
            canvas.drawRoundRect(timeBlock.getRectFBg(4), 6, 6, mBgPaint);
            canvas.drawRoundRect(timeBlock.getRectFBg(5), 6, 6, mBgPaint);
            inited = true;
        }

        //绘制时间
        canvas.drawText(formatNumH(hour), timeBlock.getRectFBg(0).centerX(), timeBlock.getBaseLineY(), mTextPaint);
        canvas.drawText(formatNumL(hour), timeBlock.getRectFBg(1).centerX(), timeBlock.getBaseLineY(), mTextPaint);

        canvas.drawText(":", timeBlock.getRectDivBg(2).centerX(), timeBlock.getBaseLineY(), mDivPaint);

        canvas.drawText(formatNumH(minute), timeBlock.getRectFBg(2).centerX(), timeBlock.getBaseLineY(), mTextPaint);
        canvas.drawText(formatNumL(minute), timeBlock.getRectFBg(3).centerX(), timeBlock.getBaseLineY(), mTextPaint);

        canvas.drawText(":", timeBlock.getRectDivBg(4).centerX(), timeBlock.getBaseLineY(), mDivPaint);

        canvas.drawText(formatNumH(second), timeBlock.getRectFBg(4).centerX(), timeBlock.getBaseLineY(), mTextPaint);
        canvas.drawText(formatNumL(second), timeBlock.getRectFBg(5).centerX(), timeBlock.getBaseLineY(), mTextPaint);

    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int width;
        int height;

        //计算控件的绘制的宽度值
        if (widthMode == MeasureSpec.EXACTLY) {
            // Parent has told us how big to be. So be it.
            width = widthSize;
        } else {
            width = getDesiredWidth();
            if (widthMode == MeasureSpec.AT_MOST) {
                width = Math.min(widthSize, width);
            }
        }
        //计算控件的绘制的高度值
        if (heightMode == MeasureSpec.EXACTLY) {
            // Parent has told us how big to be. So be it.
            height = heightSize;
        } else {
            height = getDesiredHeight();
            if (heightMode == MeasureSpec.AT_MOST) {
                height = Math.min(heightSize, height);
            }
        }

        setMeasuredDimension(width, height);
    }

    public void setOnTickListener(OnTickListener tickListener) {
        this.tickListener = tickListener;
    }

    /**
     * A callback that notifies when the chronometer has incremented on its own.
     */
    public interface OnTickListener {

        /**
         * Notification that the chronometer has changed.
         */
        void onTick(CountDownView downView);

        void onComplete(CountDownView downView);
    }

    //显示块
    class TimeBlock {
        Rect bounds;
        Rect divBounds;
        Rect tempRect;
        private float paddingLeft;
        private float paddingTop;
        private float paddingRight;
        private float paddingBottom;
        private float marginLeft;
        private float marginTop;
        private float marginRight;
        private float marginBottom;
        private float width;
        private float height;

        protected TimeBlock() {
            tempRect = new Rect();
            bounds = new Rect();
            divBounds = new Rect();
            mTextPaint.getTextBounds("8", 0, 1, bounds);//注意选择不同的字做测量所得到的值是不一样的（TODO 取十个数的最大值)
            mDivPaint.getTextBounds(":", 0, 1, divBounds);
            this.paddingLeft = dp2px(getContext(), 4);
            this.paddingTop = dp2px(getContext(), 4);
            this.paddingRight = dp2px(getContext(), 4);
            this.paddingBottom = dp2px(getContext(), 4);

            this.marginLeft = dp2px(getContext(), 2);
            this.marginTop = dp2px(getContext(), 2);
            this.marginRight = dp2px(getContext(), 2);
            this.marginBottom = dp2px(getContext(), 2);
            initWidth();
            initHeight();

        }


        protected Rect getRectDivBg(int index) {

            Rect rect = getRectBg();
            rect.left = (width() * index);
            rect.top = (int) (marginTop);
            rect.right = (width() * index);
            rect.bottom = (int) (height() - marginBottom);
            if (index >= 2) {
                rect.right += getDivWidth();
            }
            if (index >= 4) {
                rect.left += getDivWidth();
                rect.right += getDivWidth();
            }
            return rect;
        }

        protected RectF getRectFBg(int index) {
            if (rectF == null) {
                rectF = new RectF();
            }
            rectF.set(getRectBg(index));
            return rectF;
        }

        protected Rect getRectBg(int index) {

            Rect rect = getRectBg();
            rect.left = (int) (width() * index + marginLeft);
            rect.top = (int) (marginTop);
            rect.right = (int) (width() * (index + 1) - marginRight);
            rect.bottom = (int) (height() - marginBottom);
            if (index >= 2) {
                rect.left += getDivWidth();
                rect.right += getDivWidth();

            }
            if (index >= 4) {
                rect.left += getDivWidth();
                rect.right += getDivWidth();
            }
            return rect;
        }

        protected int getDivWidth() {
            return (int) (divBounds.width() + paddingLeft + paddingRight);
        }


        protected Rect getRectBg() {
            if (tempRect == null) {
                tempRect = new Rect();
            }
            Rect rect = tempRect;
            rect.left = 0;
            rect.top = 0;
            rect.right = width();
            rect.bottom = height();

            return rect;
        }

        //控件宽（包括内外距）
        private int initWidth() {
            int result = bounds.width();
            result += marginLeft + marginRight;
            result += paddingLeft + paddingRight;
            width = result;
            return result;
        }

        //控件高(包括内外距)
        protected int initHeight() {
            int result = bounds.height();
            result += marginTop + marginBottom;
            result += paddingTop + paddingBottom;
            height = result;
            return result;
        }

        //控件宽（包括内外距）
        protected int width() {
            return (int) width;
        }

        //控件高(包括内外距)
        protected int height() {
            return (int) height;
        }

        protected int getBaseLineY() {
            int result = -bounds.top;
            result += marginTop + paddingTop;
            return result;
        }

    }

}
